package com.ysh.smartplatform.websocket;

import com.ysh.smartplatform.event.DeviceCommandEvent;
import com.ysh.smartplatform.event.DeviceStatusEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 袁胜虎 on 2022/9/13 16:52
 */
@Component
public class PowerCommandWebSocket extends TextWebSocketHandler {
    private ApplicationContext applicationContext;

    @Autowired
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    private Map<String, WebSocketSession> allClients = new HashMap<>();

    /**
     * 连接成功时执行
     * @param session
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        //我们的目的最终是为了控制设备,所以我们必须知道设备的会话是什么,所以在这里我们必须把会话保存
        //我们还是约定在地址的最后一位拼接我们的设备的编号
        String path = session.getUri().getPath();
        String deviceId = path.substring(path.lastIndexOf("/") + 1);
        session.getAttributes().put("deviceId",deviceId);
        //以设备的id作为key,将会话保存
        WebSocketSession currenSession = allClients.get(deviceId);
        if (currenSession != null && currenSession.isOpen()){
            currenSession.close();
        }
        allClients.put(deviceId,session);
        //当设备上线后,我们需要更新设备的状态为在线
        applicationContext.publishEvent(new DeviceStatusEvent(deviceId,DeviceStatusEvent.Status.ONLINE));
    }

    /**
     * 关闭链接时执行
     * @param session
     * @param status
     * @throws Exception
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        //如果一个连接关闭了,说明会话结束,应该从allCilent中删除
        String deviceId =(String) session.getAttributes().get("deviceId");
        allClients.remove(deviceId);
        //当设备离线的时候我们需要将设备的状态改成离线
        applicationContext.publishEvent(new DeviceStatusEvent(deviceId,DeviceStatusEvent.Status.OFFLINE));
    }
    @EventListener
    @Async
    public void onCommand(DeviceCommandEvent event){
        String deviceId = event.getDeviceId();
        //根据设备id获取到会话
        WebSocketSession webSocketSession = allClients.get(deviceId);
        if (webSocketSession != null && webSocketSession.isOpen()){
            try {
                webSocketSession.sendMessage(new TextMessage(event.getCommand()));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
